/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bsc.minacommand.annotation;


import com.bsc.minacommand.common.Constants;
import com.bsc.util.datas.StringUtil;
import com.bsc.util.datas.Transcoding;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.mina.core.buffer.IoBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author penn
 */
public class Resolve<T> implements AbstractResolve<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(Resolve.class);

    /**
     *
     * @param clazz
     * @param bytes
     * @return T 使用反射根据对象注解将字节流封装成对象
     */
    public T ResolveByte(Class<T> clazz, byte[] bytes) {
        try {
            Field[] fields = clazz.getFields();
            //初始化对象
            T newObject = clazz.newInstance();
            int startIndex = 0;
            for (Field field : fields) {
                //验证变量是否添加VariableInfo注解
                if (field.isAnnotationPresent(VariableInfo.class)) {
                    //获取注解
                    VariableInfo annotation = field.getAnnotation(VariableInfo.class);       
                    //该字段是否需要解析
                    if(!annotation.isOpen()){
                        continue;
                    }
                    //数据长度
                    int datalength = annotation.length();
                    //如果是可变字段
                    if (annotation.vary()) {
                        datalength = Transcoding.byteToInt(StringUtil.getPartByte(bytes, startIndex, annotation.length()));
                        startIndex = startIndex + annotation.length();
                    }
                    LOGGER.debug(field.getName() + "===" + startIndex + "====" + datalength);
                    //获取数据
                    byte[] newbyte = StringUtil.getPartByte(bytes, startIndex, datalength);
                    //设置数据起始点
                    startIndex = startIndex + datalength;
                    LOGGER.debug(field.getName() + " : " + datalength);
                    //获取字段类型
                    Class classType = annotation.cType();
                    LOGGER.debug("classType: " + classType);
                    //解析String类型变量
                    if (classType.equals(String.class)) {
                        field.set(newObject, StringUtils.trim(new String(newbyte, "UTF-8")));
                        //解析Integer类型变量
                    } else if (classType.equals(Integer.class)) {
                        field.set(newObject, Transcoding.byteToInt(newbyte));
                        //解析Long类型变量
                    } else if (classType.equals(Long.class)) {
                        field.set(newObject, Transcoding.byteToLong(newbyte));
                        //解析Object类型变量
                    } else if (classType.equals(Object.class)) {
                        field.set(newObject, ResolveByte(classType, newbyte));
                        //解析List类型变量
                    } else if (classType.equals(List.class)) {
                        //嵌套解析List内对象
                        List list = ResolveList(annotation.lType(), newbyte);
                        field.set(newObject, list);
                    }
                    LOGGER.debug(field.getName()+": "+field.get(newObject));
                }
            }
            return newObject;
        } catch (Exception e) {
            LOGGER.error("ResolveByte command is error!", e);
        }
        return null;
    }

    /**
     *
     * @param clazz
     * @param bytes
     * @return List 解析List内部对象
     *
     */
    private List ResolveList(Class<T> clazz, byte[] bytes) {
        List list = new LinkedList<T>();
        //数据起始点
        int startIndex = 0;
        //获取List中对象数据体
        byte[] allbyte = StringUtil.getPartByte(bytes, Constants.COMMAND_VAR_LENGTH, bytes.length - Constants.COMMAND_VAR_LENGTH);
        
        //是否解析完毕
        boolean isover = false;
        while (!isover) {
            int objlength = Transcoding.byteToInt(StringUtil.getPartByte(allbyte, startIndex, 4));
            if(objlength == 0){
                break;
            }
            startIndex = startIndex + 4;
            byte[] objbyte = StringUtil.getPartByte(allbyte, startIndex, objlength);

            //解析数据
            list.add(ResolveByte(clazz, objbyte));
            //数据起始点累加，以便循环
            startIndex = startIndex + objlength;
        }
        return list;
    }

    /**
     *
     * @param obj
     * @return 将对象封装成 T(默认byte数组)
     */
    public T ResolveObject(Object obj) {
        IoBuffer buffer = IoBuffer.allocate(128);
        buffer.setAutoExpand(true);
        try {
            Class clazz = obj.getClass();
            Field[] fields = clazz.getFields();
            for (Field field : fields) {

                //验证变量是否添加VariableInfo注解
                if (field.isAnnotationPresent(VariableInfo.class)) {
                    //获取注解
                    VariableInfo annotation = field.getAnnotation(VariableInfo.class);

                    //获取字段类型
                    Class classType = annotation.cType();
                    //封装String类型变量
                    if (classType.equals(String.class)) {
                        //获取变量值
                        String var = (String) field.get(obj);
                        //如果是可变字段
                        if (annotation.vary()) {
                            buffer.put(Transcoding.intToByte(var.getBytes("UTF-8").length));
                            buffer.put(var.getBytes("UTF-8"));
                        } else {
                            buffer.put(StringUtil.getBuild_byte(var, annotation.length()));
                        }

                        //封装Integer类型变量
                    } else if (classType.equals(Integer.class)) {
                        int var = (Integer) field.get(obj);
                        buffer.put(Transcoding.intToByte(var));
                        //封装Long类型变量
                    } else if (classType.equals(Long.class)) {
                        //封装Object类型变量
                    } else if (classType.equals(Object.class)) {
                        Object var = field.get(obj);
                        byte[] objByte = (byte[]) ResolveObject(var);
                        buffer.put(Transcoding.intToByte(objByte.length));
                        buffer.put(objByte);
                        //封装List类型变量
                    } else if (classType.equals(List.class)) {
                        //嵌套封装List内对象
                        IoBuffer cbuffer = IoBuffer.allocate(256);
                        cbuffer.setAutoExpand(true);
                        Class ltype = annotation.lType();
                        List var = (List) field.get(obj);
                        for (Object object : var) {
                            byte[] lbyte = (byte[]) ResolveObject(object);
                            cbuffer.put(Transcoding.intToByte(lbyte.length));
                            cbuffer.put(lbyte);
                        }
                        byte[] cbyte = cbuffer.array();
                        //List总数据长度
                        buffer.put(Transcoding.intToByte(cbyte.length + Constants.COMMAND_VAR_LENGTH));
                        //List内对象类型
                        buffer.put(StringUtil.getBuild_byte(ltype.getSimpleName(), Constants.COMMAND_VAR_LENGTH));
                        //List内对象数据体
                        buffer.put(cbyte);

                    }
                }
            }
            return (T) buffer.array();
        } catch (Exception e) {
            LOGGER.error("ResolveObject command is error!", e);
        }
        return null;
    }

}
